//! 协议编解码器

use std::collections::HashMap;
use serde::{Deserialize, Serialize};

use nacos_core::traits::{NetworkRequest, NetworkResponse};
use nacos_core::{Result, NacosError};

/// 消息类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MessageType {
    Request,
    Response,
    Heartbeat,
    DataSync,
    MemberChange,
}

/// 消息头
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageHeader {
    pub message_type: MessageType,
    pub protocol_version: String,
    pub content_type: String,
    pub content_length: usize,
    pub request_id: String,
    pub source_node: String,
    pub target_node: String,
    pub timestamp: u64,
    pub checksum: u32,
}

/// 消息体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageBody {
    pub data: Vec<u8>,
    pub metadata: HashMap<String, String>,
}

/// 完整消息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkMessage {
    pub header: MessageHeader,
    pub body: MessageBody,
}

impl NetworkMessage {
    /// 创建新的消息
    pub fn new(
        message_type: MessageType,
        request_id: String,
        source_node: String,
        target_node: String,
        data: Vec<u8>,
    ) -> Self {
        let timestamp = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs();

        let checksum = crc32fast::hash(&data);

        Self {
            header: MessageHeader {
                message_type,
                protocol_version: "1.0".to_string(),
                content_type: "application/json".to_string(),
                content_length: data.len(),
                request_id,
                source_node,
                target_node,
                timestamp,
                checksum,
            },
            body: MessageBody {
                data,
                metadata: HashMap::new(),
            },
        }
    }

    /// 验证消息完整性
    pub fn validate(&self) -> Result<()> {
        let calculated_checksum = crc32fast::hash(&self.body.data);
        
        if calculated_checksum != self.header.checksum {
            return Err(NacosError::Protocol("消息校验失败".to_string()));
        }

        if self.body.data.len() != self.header.content_length {
            return Err(NacosError::Protocol("消息长度不匹配".to_string()));
        }

        Ok(())
    }

    /// 转换为网络请求
    pub fn to_network_request(&self,
    ) -> Result<NetworkRequest> {
        Ok(NetworkRequest {
            request_id: self.header.request_id.clone(),
            source_node_id: self.header.source_node.clone(),
            module: "protocol".to_string(),
            r#type: match self.header.message_type {
                MessageType::Request => "request".to_string(),
                MessageType::Response => "response".to_string(),
                MessageType::Heartbeat => "heartbeat".to_string(),
                MessageType::DataSync => "data_sync".to_string(),
                MessageType::MemberChange => "member_change".to_string(),
            },
            body: self.body.data.clone(),
        })
    }

    /// 从网络请求创建消息
    pub fn from_network_request(
        request: &NetworkRequest,
        source_node: String,
        target_node: String,
    ) -> Result<Self> {
        let message_type = match request.r#type.as_str() {
            "request" => MessageType::Request,
            "response" => MessageType::Response,
            "heartbeat" => MessageType::Heartbeat,
            "data_sync" => MessageType::DataSync,
            "member_change" => MessageType::MemberChange,
            _ => return Err(NacosError::Protocol(format!("未知消息类型: {}", request.r#type))),
        };

        Ok(Self::new(
            message_type,
            request.request_id.clone(),
            source_node,
            target_node,
            request.body.clone(),
        ))
    }

    /// 转换为网络响应
    pub fn to_network_response(&self,
    ) -> Result<NetworkResponse> {
        let success = match self.header.message_type {
            MessageType::Response => true,
            _ => false,
        };

        Ok(NetworkResponse {
            request_id: self.header.request_id.clone(),
            success,
            error_code: 0,
            error_message: String::new(),
            body: self.body.data.clone(),
        })
    }

    /// 序列化为字节数组
    pub fn serialize(&self,
    ) -> Result<Vec<u8>> {
        bincode::serialize(self)
            .map_err(|e| NacosError::Protocol(format!("序列化失败: {}", e)))
    }

    /// 从字节数组反序列化
    pub fn deserialize(data: &[u8]) -> Result<Self> {
        bincode::deserialize(data)
            .map_err(|e| NacosError::Protocol(format!("反序列化失败: {}", e)))
    }
}

/// 编解码器trait
pub trait Codec {
    /// 编码消息
    fn encode(&self,
        message: &NetworkMessage,
    ) -> Result<Vec<u8>>;

    /// 解码消息
    fn decode(&self,
        data: &[u8],
    ) -> Result<NetworkMessage>;
}

/// JSON编解码器
pub struct JsonCodec;

impl Codec for JsonCodec {
    fn encode(
        &self,
        message: &NetworkMessage,
    ) -> Result<Vec<u8>> {
        serde_json::to_vec(message)
            .map_err(|e| NacosError::Protocol(format!("JSON编码失败: {}", e)))
    }

    fn decode(
        &self,
        data: &[u8],
    ) -> Result<NetworkMessage> {
        serde_json::from_slice(data)
            .map_err(|e| NacosError::Protocol(format!("JSON解码失败: {}", e)))
    }
}

/// 二进制编解码器
pub struct BinaryCodec;

impl Codec for BinaryCodec {
    fn encode(
        &self,
        message: &NetworkMessage,
    ) -> Result<Vec<u8>> {
        message.serialize()
    }

    fn decode(
        &self,
        data: &[u8],
    ) -> Result<NetworkMessage> {
        NetworkMessage::deserialize(data)
    }
}

/// 编解码器工厂
pub struct CodecFactory;

impl CodecFactory {
    /// 根据格式创建编解码器
    pub fn create_codec(format: &str) -> Box<dyn Codec> {
        match format {
            "json" => Box::new(JsonCodec),
            "binary" => Box::new(BinaryCodec),
            _ => Box::new(JsonCodec), // 默认使用JSON
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_network_message_serialization() {
        let message = NetworkMessage::new(
            MessageType::Request,
            "test-123".to_string(),
            "node-1".to_string(),
            "node-2".to_string(),
            b"test data".to_vec(),
        );

        // 测试验证
        assert!(message.validate().is_ok());

        // 测试序列化/反序列化
        let serialized = message.serialize().unwrap();
        let deserialized = NetworkMessage::deserialize(&serialized).unwrap();
        
        assert_eq!(message.header.request_id, deserialized.header.request_id);
        assert_eq!(message.body.data, deserialized.body.data);
    }

    #[test]
    fn test_json_codec() {
        let message = NetworkMessage::new(
            MessageType::Response,
            "test-456".to_string(),
            "node-1".to_string(),
            "node-2".to_string(),
            b"json test".to_vec(),
        );

        let codec = JsonCodec;
        let encoded = codec.encode(&message).unwrap();
        let decoded = codec.decode(&encoded).unwrap();

        assert_eq!(message.header.request_id, decoded.header.request_id);
    }

    #[test]
    fn test_network_message_conversion() {
        let request = NetworkRequest {
            request_id: "test-789".to_string(),
            source_node_id: "node-1".to_string(),
            module: "test".to_string(),
            r#type: "request".to_string(),
            body: b"conversion test".to_vec(),
        };

        let message = NetworkMessage::from_network_request(
            &request,
            "node-1".to_string(),
            "node-2".to_string(),
        ).unwrap();

        let back_to_request = message.to_network_request().unwrap();
        assert_eq!(request.request_id, back_to_request.request_id);
    }
}